package org.lex.ftplist.core;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

import javax.swing.DefaultBoundedRangeModel;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.lex.collection.tree.ITreeNode;
import org.lex.collection.tree.TreeNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FtpList extends DefaultBoundedRangeModel {
	private Logger log = LoggerFactory.getLogger(FtpList.class);

	public ITreeNode list(FTPClient ftp, String root) throws IOException {
		// progress
		this.setMinimum(0);
		this.setMaximum(1);
		// progress

		ftp.changeWorkingDirectory(root);
		ftp.changeToParentDirectory();

		FTPFile froot = new FTPFile();
		froot.setName(root);
		TreeNode rootNode = new TreeNode(froot);

		// <path, node>
		Map<String, ITreeNode> nodes = new HashMap<String, ITreeNode>();
		nodes.put(root, rootNode);

		Stack<String> stack = new Stack<String>();
		stack.push(root);
		while (false == stack.isEmpty()) {
			String current = stack.pop();
			// progress
			this.setValue(this.getValue() + 1);
			// progress
			log.debug("current directory=[" + current + "]");
			ftp.changeWorkingDirectory(current);

			String pwd = ftp.printWorkingDirectory();
			log.debug("list directory=[" + pwd + "]");
			ITreeNode parent = nodes.get(pwd);
			FTPFile[] files = ftp.listFiles();
			if (null == files || 0 == files.length) {
				continue;
			}
			for (FTPFile file : files) {
				String name = file.getName();
				if (name.equals(".") || name.equals("..")) {
					continue;
				}

				String path = newPath(pwd, name);
				log.debug("current file path=[" + path + "]");
				TreeNode node = new TreeNode(file);
				node.setParent(parent);
				nodes.put(path, node);

				if (file.isDirectory()) {
					stack.push(path);
					// progress
					this.setMaximum(this.getMaximum() + 1);
					// progress
				}
			}
		}

		return rootNode;
	}

	private String newPath(String parent, String child) {
		StringBuilder buf = new StringBuilder();
		int len = parent.length();
		if ('/' == parent.charAt(len - 1)) {
			parent = parent.substring(0, len - 1);
		}
		buf.append(parent);
		buf.append('/');
		if ('/' == child.charAt(0)) {
			child = child.substring(1);
		}
		buf.append(child);
		return buf.toString();
	}
}
